package com.free4inno.knowledgems.controller;

import com.free4inno.knowledgems.constants.GroupConstants;
import com.free4inno.knowledgems.dao.GroupInfoDAO;
import com.free4inno.knowledgems.dao.UserDAO;
import com.free4inno.knowledgems.dao.UserGroupDAO;
import com.free4inno.knowledgems.domain.GroupInfo;
import com.free4inno.knowledgems.domain.User;
import com.free4inno.knowledgems.domain.UserGroup;
import com.free4inno.knowledgems.service.CleanResourceService;
import com.free4inno.knowledgems.constants.UserConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;

import java.sql.Timestamp;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * GroupInfoController.
 */

@Slf4j
@Controller
@RequestMapping("/")
public class GroupInfoController {

    @Autowired
    private UserGroupDAO userGroupDao;

    @Autowired
    private GroupInfoDAO groupInfoDao;

    @Autowired
    private UserDAO userDao;

    @Autowired
    private CleanResourceService cleanResourceService;

    @RequestMapping("/groupinfo")
    public String getGroup(@RequestParam("groupid") int groupId, Map param, HttpSession session) {
        log.info(this.getClass().getName()+"----in----" + "获取群组信息(groupinfo)" + "----" + session.getAttribute(UserConstants.USER_ID));
        GroupInfo groupInfo = groupInfoDao.findById(groupId).orElse(new GroupInfo());

        int permission1 = 0;
        int memberNum = 0;
        int flag = 0; //是否有组长

        List<UserGroup> groupsMembers = userGroupDao.findByGroupId(groupId);
        if (groupsMembers != null) {
            memberNum = groupsMembers.size();
            groupInfo.setMemberNum(memberNum);
            for (UserGroup leaderGroup : groupsMembers) {
                permission1 = leaderGroup.getPermission();
                User user = userDao.findById(leaderGroup.getUserId()).orElse(new User());
                leaderGroup.setRealName(user.getRealName());
                if (permission1 == 1) {
                    flag = 1;
                    user = userDao.findById(leaderGroup.getUserId()).orElse(new User());
                    groupInfo.setLeader(user.getRealName());
                }
                if (flag == 0) {
                    groupInfo.setLeader(GroupConstants.GROUP_LEADER);
                }
            }
        }

        if (groupInfo.getGroupInfo() == "") {
            groupInfo.setGroupInfo(GroupConstants.GROUP_INTRODUCTION);
        }

        if (groupInfo.getLeader() == "") {
            groupInfo.setLeader(GroupConstants.GROUP_LEADER);
        }

        String userName = userDao.findById((int) session.getAttribute(UserConstants.USER_ID)).get().getRealName();
        int permission = 0;
        if (userGroupDao.existsByGroupIdAndUserId(groupId, (int) session.getAttribute(UserConstants.USER_ID))) {
            permission = userGroupDao.findByGroupIdAndUserId(groupId, (int) session.getAttribute(UserConstants.USER_ID)).get().getPermission();
        }

        int roleID = (int) session.getAttribute(GroupConstants.ROLE_ID);

        param.put(GroupConstants.GROUP_ID, groupId);
        param.put(GroupConstants.GROUP_INFO, groupInfo);
        param.put(GroupConstants.GROUP_MEMBERS, groupsMembers);
        param.put(GroupConstants.USER_NAME, userName);
        param.put(GroupConstants.USER_PERMISSION, permission);
        param.put(GroupConstants.ROLE_IDNUM, roleID);

        log.info(this.getClass().getName()+"----out----" + "跳转到群组信息页" + "----" + session.getAttribute(UserConstants.USER_ID));
        return "group/groupinfo";
    }

    @RequestMapping("/groupmanage")
    public String groupmanage(HttpSession session) {
        log.info(this.getClass().getName()+"----in----" + "群组管理(groupmanage)" + "----" + session.getAttribute(UserConstants.USER_ID));
        if (session.getAttribute(GroupConstants.ROLE_ID).equals(1) || session.getAttribute(GroupConstants.ROLE_ID).equals(2)) {
            log.info(this.getClass().getName()+"----out----" + "用户具有管理群组权限" + "----" + session.getAttribute(UserConstants.USER_ID));
            return "/group/groupManagement";
        } else {
            log.info(this.getClass().getName()+"----out----" + "用户不具有管理群组权限" + "----" + session.getAttribute(UserConstants.USER_ID));
            return "redirect:/";
        }
    }

    @RequestMapping("/groupManagement")
    public String getAllGroups(Map param,
                               @RequestParam("page") int currentPage,
                               @RequestParam("search") String searchKey,
                               HttpSession session) {
        log.info(this.getClass().getName()+"----in----" + "群组管理页面(groupManagement)" + "----" + session.getAttribute(UserConstants.USER_ID));

        int maxItems = 14;
        int pageNum = 0;
        int searchedGroupNum = 0;
        List<GroupInfo> groupInfos = new ArrayList<>();

        // judge search
        if (searchKey.isEmpty()){
            // no search and query all through page
            Sort sort = Sort.by(Sort.Direction.ASC, "id");
            Pageable pageable = PageRequest.of(currentPage - 1, maxItems, sort);
            Page<GroupInfo> groupPage = groupInfoDao.findAll(pageable);

            // get content and page number
            pageNum = groupPage.getTotalPages();
            groupInfos = groupPage.getContent();
            searchedGroupNum = groupPage.getNumberOfElements();

            // get leaders name
            // 1. build a leaders' hash set to De-duplication
            HashSet<Integer> leadersId = new HashSet<>();
            for (GroupInfo groupInfo : groupInfos) {
                Integer leaderId = userGroupDao.findByGroupIdAndPermission(groupInfo.getId(), 1).get().getUserId();
                leadersId.add(leaderId);
                groupInfo.setLeader(Integer.toString(leaderId));
            }
            // 2. build a hash map to save all leaders name
            HashMap<Integer, String> leadersName = new HashMap<>();
            for (Integer leaderId : leadersId){
                String leaderName = userDao.findById(leaderId).get().getRealName();
                leadersName.put(leaderId, leaderName);
            }
            // 3. use names in map, reduce interactions with DB
            for (GroupInfo groupInfo : groupInfos) {
                String leaderName = leadersName.get(Integer.parseInt(groupInfo.getLeader()));
                groupInfo.setLeader(leaderName);
            }
        } else {
            // get all
            groupInfos = groupInfoDao.findAll();
            for (GroupInfo groupInfo : groupInfos) {
                groupInfo.setLeader(userDao.findById(userGroupDao.findByGroupIdAndPermission(groupInfo.getId(), 1).get().getUserId()).get().getRealName());
            }
            // do search
            List<GroupInfo> beforeSearchGroupList = groupInfos;
            List<GroupInfo> searchedGroupList = new ArrayList<>();
            for (GroupInfo groupInfo : beforeSearchGroupList) {
                Pattern p = Pattern.compile(searchKey, Pattern.CASE_INSENSITIVE);
                Matcher m1 = p.matcher(groupInfo.getGroupName());
                Matcher m2 = p.matcher(groupInfo.getLeader());

                if (m1.find() || m2.find()) {
                    searchedGroupList.add(groupInfo);
                }
            }
            // manual page
            pageNum = searchedGroupList.size() / maxItems;
            int remainNum = searchedGroupList.size() % maxItems;
            if (remainNum > 0) {
                pageNum++;
            }
            List<GroupInfo> pagedGroupList;
            if (currentPage * maxItems < searchedGroupList.size()) {
                pagedGroupList = searchedGroupList.subList((currentPage - 1) * maxItems, currentPage * maxItems);
            } else {
                pagedGroupList = searchedGroupList.subList((currentPage - 1) * maxItems, searchedGroupList.size());
            }

            groupInfos = pagedGroupList;
            searchedGroupNum = searchedGroupList.size();
        }

        // group list
        param.put(GroupConstants.GROUP_LIST, groupInfos);
        // page info
        param.put(GroupConstants.MAX_PAGES, pageNum);
        param.put(GroupConstants.CURRENT_PAGE, currentPage);
        // search info
        param.put(GroupConstants.SEARCH, searchKey);
        param.put(GroupConstants.SEARCHED_GROUPNUM, searchedGroupNum);

        log.info(this.getClass().getName()+"----out----" + "跳转到群组管理页面" + "----" + session.getAttribute(UserConstants.USER_ID));
        return "group/_groupList";
    }

    @RequestMapping("/getMember")
    public String getMember(@RequestParam("groupId") int groupId,
                            Map param, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"获取群组成员(getMember)"+"----"+session.getAttribute(UserConstants.USER_ID));
        List<UserGroup> memberList = userGroupDao.findByGroupId(groupId);
        for (UserGroup userGroup : memberList) {
            String userName = userDao.findById(userGroup.getUserId()).get().getRealName();
            userGroup.setRealName(userName);
        }
        int permission = 0;
        if (userGroupDao.existsByGroupIdAndUserId(groupId, (int) session.getAttribute(UserConstants.USER_ID))) {
            permission = userGroupDao.findByGroupIdAndUserId(groupId, (int) session.getAttribute(UserConstants.USER_ID)).get().getPermission();
        }

        int roleID = (int) session.getAttribute(GroupConstants.ROLE_ID);

        param.put(GroupConstants.MEMBER_LIST, memberList);
        param.put(GroupConstants.GROUP_ID, groupId);
        param.put(GroupConstants.USER_PERMISSION, permission);
        param.put(GroupConstants.ROLE_IDNUM, roleID);

        log.info(this.getClass().getName()+"----out----"+"返回群组成员列表"+"----"+session.getAttribute(UserConstants.USER_ID));
        return "group/_member";
    }

    @ResponseBody
    @PostMapping("/setLeader")
    public String setLeader(@RequestParam("groupId") int groupId,
                           @RequestParam("userId") int userId, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"设置群主(setLeader)"+"----"+session.getAttribute(UserConstants.USER_ID));
        UserGroup userGroup = userGroupDao.findByGroupIdAndPermission(groupId, 1).orElse(new UserGroup());
        userGroup.setPermission(0);
        userGroupDao.save(userGroup);
        userGroup = userGroupDao.findByGroupIdAndUserId(groupId, userId).orElse(new UserGroup());
        userGroup.setPermission(1);
        userGroupDao.save(userGroup);
        String result = "ok";
        log.info(this.getClass().getName()+"----out----"+"设置成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));
        return result;
    }

    @ResponseBody
    @PostMapping("/setAdmin")
    public String setAdmin(@RequestParam("groupId") int groupId,
                           @RequestParam("userId") int userId, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"设置群管理(setAdmin)"+"----"+session.getAttribute(UserConstants.USER_ID));
        UserGroup userGroup = userGroupDao.findByGroupIdAndUserId(groupId, userId).orElse(new UserGroup());
        userGroup.setPermission(2);
        userGroupDao.save(userGroup);
        String result = "ok";
        log.info(this.getClass().getName()+"----out----"+"设置成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));
        return result;
    }

    @ResponseBody
    @PostMapping("/deleteGroup")
    public String deleteGroup(@RequestParam("groupId") Integer groupId, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"删除群组(deleteGroup)"+"----"+session.getAttribute(UserConstants.USER_ID));
        groupInfoDao.deleteById(groupId);
        userGroupDao.deleteAllByGroupId(groupId);
        cleanResourceService.cleanGroupIdInResource(groupId.toString());
        String result = "ok";
        log.info(this.getClass().getName()+"----out----"+"删除成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));
        return result;
    }

    @ResponseBody
    @PostMapping("/addGroup")
    public String addGroup(@RequestParam("name") String name,
                           @RequestParam("leaderName") String leaderName, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"新建群组(addGroup)"+"----"+session.getAttribute(UserConstants.USER_ID));

        GroupInfo groupInfo = new GroupInfo();
        groupInfo.setGroupName(name);
        groupInfo.setCreateTime(new Timestamp(System.currentTimeMillis()));
        groupInfo.setEditTime(new Timestamp(System.currentTimeMillis()));
        groupInfo.setCropId(0);
        groupInfoDao.save(groupInfo);

        UserGroup userGroup = new UserGroup();
        userGroup.setUserId(userDao.findByRealName(leaderName).get().getId());
        userGroup.setGroupId(groupInfoDao.findTopByOrderByIdDesc().getId());
        userGroup.setPermission(1);
        userGroupDao.save(userGroup);

        String result = "ok";
        log.info(this.getClass().getName()+"----out----"+"新建成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));
        return result;
    }

    @ResponseBody
    @PostMapping("/cancelAdmin")
    public String cancelAdmin(@RequestParam("groupId") int groupId,
                              @RequestParam("userId") int userId, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"取消群管理(cancelAdmin)"+"----"+session.getAttribute(UserConstants.USER_ID));

        UserGroup userGroup = userGroupDao.findByGroupIdAndUserId(groupId, userId).orElse(new UserGroup());
        userGroup.setPermission(0);
        userGroupDao.save(userGroup);
        String result = "ok";
        log.info(this.getClass().getName()+"----out----"+"操作成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));
        return result;
    }

    @ResponseBody
    @PostMapping("/addMember")
    public String addMember(@RequestParam("groupId") int groupId,
                            @RequestParam("userAccount") String userAccount, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"添加群成员(addMember)"+"----"+session.getAttribute(UserConstants.USER_ID));

        UserGroup userGroup = new UserGroup();
        int userId = userDao.findByAccount(userAccount).get().getId();
        userGroup.setUserId(userId);
        userGroup.setGroupId(groupId);
        userGroup.setPermission(0);
        userGroupDao.save(userGroup);
        String result = "ok";
        log.info(this.getClass().getName()+"----out----"+"操作成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));
        return result;
    }

    @ResponseBody
    @PostMapping("/deleteMember")
    public String deleteMember(@RequestParam("groupId") int groupId,
                               @RequestParam("userId") int userId, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"删除群成员(deleteMember)"+"----"+session.getAttribute(UserConstants.USER_ID));

        userGroupDao.deleteByGroupIdAndUserId(groupId, userId);
        String result = "ok";
        log.info(this.getClass().getName()+"----out----"+"操作成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));
        return result;
    }

    @ResponseBody
    @PostMapping("/newEditGroup")
    public String newEditGroup(@RequestParam("groupId") int groupId,
                               @RequestParam("newName") String newName, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"新建编辑群组(newEditGroup)"+"----"+session.getAttribute(UserConstants.USER_ID));

        GroupInfo groupInfo = groupInfoDao.findById(groupId).orElse(new GroupInfo());
        groupInfo.setGroupName(newName);
        groupInfoDao.save(groupInfo);
        String result = "ok";
        log.info(this.getClass().getName()+"----out----"+"操作成功，返回ok"+"----"+session.getAttribute(UserConstants.USER_ID));
        return result;
    }

//    @ResponseBody
//    @PostMapping("/getNames")
//    public List<String> getNames(@RequestParam("groupId") int groupId) {
//        List<User> userList = userDao.findAll();
//        List<String> nameList = new ArrayList<>();
//        for(User user : userList)
//        {
//            String name = user.getRealName();
//            nameList.add(name);
//        }
//
//        List<UserGroup> alreadyMemberList = userGroupDao.findByGroupId(groupId);
//        List<String> alreadyMemberNameList = new ArrayList<String>();
//        for(UserGroup userGroup : alreadyMemberList)
//        {
//            String name = userDao.findById(userGroup.getUserId()).get().getRealName();
//            alreadyMemberNameList.add(name);
//        }
//
//        for(int j = 0; j < nameList.size(); j++){
//            if(alreadyMemberNameList.contains(nameList.get(j))){
//                nameList.remove(j);
//                j--;
//            }
//        }
//        return nameList;
//    }

    @ResponseBody
    @PostMapping("/getNames")
    public List<String> getNames(@RequestParam("groupId") int groupId, HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"获取不在群内用户名(getNames)"+"----"+session.getAttribute(UserConstants.USER_ID));

        List<User> userList = userDao.findAll();
        List<String> nameList = new ArrayList<>();
        for (User user : userList) {
            String name = user.getRealName();
            nameList.add(name);
        }

        List<UserGroup> alreadyMemberList = userGroupDao.findByGroupId(groupId);
        List<String> alreadyMemberNameList = new ArrayList<String>();
        for (UserGroup userGroup : alreadyMemberList) {
            String name = userDao.findById(userGroup.getUserId()).get().getRealName();
            alreadyMemberNameList.add(name);
        }

        for (int j = 0; j < nameList.size(); j++) {
            if (alreadyMemberNameList.contains(nameList.get(j))) {
                nameList.remove(j);
                j--;
            }
        }

        //此处暂时未考虑重名情况
        for (int j = 0; j < nameList.size(); j++) {
            String name = nameList.get(j);
            String account = userDao.findByRealName(name).get().getAccount();
            String mail = userDao.findByRealName(name).get().getMail();
            nameList.set(j, name + " | " + account + " | " + mail);
        }

        log.info(this.getClass().getName()+"----out----"+"获取成功，返回名单"+"----"+session.getAttribute(UserConstants.USER_ID));
        return nameList;
    }

    @ResponseBody
    @PostMapping("/getAllNames")
    public List<String> getAllNames(HttpSession session) {
        log.info(this.getClass().getName()+"----in----"+"获取全部用户名(getAllNames)"+"----"+session.getAttribute(UserConstants.USER_ID));

        List<User> userList = userDao.findAll();
        List<String> nameList = new ArrayList<String>();
        for (User user : userList) {
            String name = user.getRealName();
            nameList.add(name);
        }

        //此处暂时未考虑重名情况
        for (int j = 0; j < nameList.size(); j++) {
            String name = nameList.get(j);
            String account = userDao.findByRealName(name).get().getAccount();
            String mail = userDao.findByRealName(name).get().getMail();
            nameList.set(j, name + " | " + account + " | " + mail);
        }

        log.info(this.getClass().getName()+"----out----"+"获取成功，返回名单"+"----"+session.getAttribute(UserConstants.USER_ID));
        return nameList;
    }

}

